﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace AB.Common
{
    /// <summary>
    /// IQueryable扩展
    /// </summary>
    public static class IQueryableExtend
    {
        /// <summary>
        /// WHERE条件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dbset"></param>
        /// <param name="whereLambda"></param>
        /// <param name="isNoTracking"></param>
        /// <param name="dynamicsLambda"></param>
        /// <returns></returns>
        public static IQueryable<T> WHERE<T>(this DbSet<T> dbset, Expression<Func<T, bool>> whereLambda, bool isNoTracking = true, bool dynamicsLambda = false) where T : class, new()
        {
            IQueryable<T> query;
            if (dynamicsLambda)
            {
                query = dbset.Where<T>(whereLambda.Compile()).AsQueryable<T>();
            }
            else
            {
                query = dbset.Where<T>(whereLambda);
            }

            if (isNoTracking)
            {
                query = query.AsNoTracking();
            }
            return query;
        }
        /// <summary>
        /// SORT排序
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="s"></typeparam>
        /// <param name="queryable"></param>
        /// <param name="orderByLambda"></param>
        /// <param name="isAsc"></param>
        /// <returns></returns>
        public static IQueryable<T>  SORT<T,s>(this IQueryable<T> queryable, Expression<Func<T, s>> orderByLambda, bool isAsc) where T : class, new()
        {
            if (orderByLambda != null)
            {
                if (isAsc)
                {
                    queryable.OrderBy<T, s>(orderByLambda);
                }
                else
                {
                    queryable.OrderByDescending<T, s>(orderByLambda);
                }
            }
            return queryable;
        }
        /// <summary>
        /// SORT排序
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="queryable"></param>
        /// <param name="sortNameOrder"></param>
        /// <returns></returns>
        public static IQueryable<T> SORT<T>(this IQueryable<T> queryable, Dictionary<string, string> sortNameOrder) where T : class, new()
        {
            var sortExpression = Expression.Parameter(queryable.ElementType);
            foreach (var item in sortNameOrder.Reverse())
            {
                bool isAsc = true;
                if (item.Value.ToLower() == "desc")
                {
                    isAsc = false;
                }
                if (typeof(T).GetProperty(item.Key) != null)
                {
                    string orderstr = isAsc ? "OrderBy" : "OrderByDescending";
                    var selector = Expression.Lambda(Expression.PropertyOrField(sortExpression, item.Key), sortExpression);
                    queryable = (IQueryable<T>)queryable.Provider.CreateQuery(Expression.Call(typeof(Queryable), orderstr, new Type[] { queryable.ElementType, selector.Body.Type }, queryable.Expression, selector));
                }
            }
            return queryable;
        }
        /// <summary>
        /// 分页
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="queryable"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="totalCount"></param>
        /// <param name="realPageIndex"></param>
        /// <returns></returns>
        public static IQueryable<T> PAGE<T>(this IQueryable<T> queryable, int pageIndex, int pageSize, out int totalCount, out int realPageIndex) where T : class, new()
        {
            totalCount = queryable.Count();
            pageSize = pageSize == 0 ? 1 : pageSize;
            pageSize = pageSize < 0 ? totalCount : pageSize;
            int maxpage = (int)Math.Ceiling(totalCount * 1.0 / pageSize);
            realPageIndex = pageIndex < 1 ? 1 : pageIndex;
            realPageIndex = pageIndex > maxpage ? maxpage : pageIndex;
            return queryable.Skip<T>((realPageIndex - 1) * pageSize).Take<T>(pageSize);
        }
        /// <summary>
        /// TOP取前几条
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="queryable"></param>
        /// <param name="top"></param>
        /// <returns></returns>
        public static IQueryable<T> TOP<T>(this IQueryable<T> queryable, int top) where T : class, new()
        {
            return queryable.Take<T>(top);
        }
    }
}
